home *** CD-ROM | disk | FTP | other *** search
- Path: chronicle.mti.sgi.com!austern
- From: kanze@gabi.gabi-soft.fr (J. Kanze)
- Newsgroups: comp.std.c++
- Subject: Re: class.union questions
- Date: 16 Feb 1996 09:15:48 PST
- Organization: GABI Software, Sarl.
- Approved: austern@isolde.mti.sgi.com
- Message-ID: <KANZE.96Feb16160724@gabi.gabi-soft.fr>
- References: <v01530501ad3e247b1270@[194.163.74.11]>
- NNTP-Posting-Host: isolde.mti.sgi.com
- X-Original-Date: 16 Feb 1996 15:07:24 GMT
- In-Reply-To: dirk@becker.adviser.com's message of 10 Feb 1996 15:39:23 GMT
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBVAwUBMSS73Ey4NqrwXLNJAQHyvQH9EyHNtQwm2URxZyG+53xFtvs2Z1JndlUf
- mh/Ox+y6n5o/JfsVr4I/5yZvrwdP8iFBp9bmuWCdpVvbq/OtDjwXfA==
- =5HFd
- Originator: austern@isolde.mti.sgi.com
-
- In article <v01530501ad3e247b1270@[194.163.74.11]>
- dirk@becker.adviser.com (Dirk Becker) writes:
-
- > The first replies to my (DB) original posting seem to have the same
- > objection against my interpretation of b). This is my major problem,
- > so I put it first now.
- >
- > James Kanze (JK) and John Max Skaller (JS) wrote:
- >
- > From the WP: [class.union]
- >
- > b) "An object of a class with a non-trivial default constructor
- > (_class.ctor_), a non-trivial copy constructor (_class.copy_),
- > a non-trivial destructor (_class.dtor_), or a non-trivial copy
- > assignment operator (_over.ass_, _class.copy_) cannot be a member
- > of a union,"
- >
- > DB> This is a major reduction of the restrictions found in ARM, where all
- > DB> kinds of constructors or assignment operators were excluded. Here is
- > DB> also a note to give the explanation by the assumption, any member
- > DB> functions and especially assignments would usually expect a correctly
- > DB> constructed object.
- >
- > JS> No. It is merely a more precise statement of the same
- > JS> restrictions using more technical terminology.
- >
- > JK> This is, in fact, exactly the restriction in the ARM. All that has
- > JK> changes is the way things are described. In the ARM, classes may or
- > JK> may not have constructors (destructors, assignment operators). In the
- > JK> current standard, *EVERY* class/struct has a copy constructor, an
- > JK> assignment operator and a destructor; the distinction is that some of
- > JK> these are trivial.
- >
- > I still disagree totally. Please tell me what I'm reading wrong.
- >
- > The ARM (mine is an early edition, 1990) does a complete restriction
- > against *any* constructor, destructor or user-defined assignment for
- > union member objects. (Section 9.5, page 182). The only explanation for
- > this rule was already summarized in my original posting, quoted above;
- > it has nothing to do with bitwise copy.
- >
- > The WP indeed allows member objects with a rich set of constructors
- > and assignment operators. It does only <g> cripple the 4 most commonly
- > used special member functions, exactly naming them, into trivialness.
- > - default constructor
- > - destructor
- > - copy constructor
- > - copy assignment
- > I assume this exact enumeration implies all other variants of constructor
- > and assignment in member objects are free for user defined versions.
-
- I'm not really sure what the restriction on constructors is meant to
- signify. If the member has a constructor, then the compiler cannot
- generate a default constructor for it. IMHO, this should imply that it
- cannot be a member, i.e.: that the words should be that member objects
- must have trivial default constructors, and not that they cannot have
- non-trivial default constructors.
-
- The problem is how to construct the union. If the union has no user
- provided constructor, then it cannot be constructed, because the
- compiler cannot generate a default constructor for it. But if the union
- has a user defined constructor? Does the user defined constructor have
- to initialize the member (presumably yes)? And what if there are two
- such members? Does the user defined constructor have to initialize both
- of them (bad news either way)?
-
- I'll admit to not having thought about the other possible assignment
- operators. Since other assignment operators do not inhibit the
- generation of the copy assignment operator, though, the additional
- freedom poses no problem.
-
- [...]
- > a) "A union shall not have base classes. A union shall not be used as
- > a base class."
- >
- > JK> Without this rule, you either break the address rule, or you impose
- > JK> some special class layout on unions.
- >
- > The union has no special class layout? I would say it is very special.
- > "a class whose member objects all begin at offset zero"
-
- Poor wording on my part. This is the address rule that must be
- maintained.
-
- > /* my sample of union inheritance */
- >
- > JK> This is generally handled better by an abstract base class and
- > JK> virtual functions.
- >
- > Sure, I like polymorphic objects. But if you have a vast amount of
- > really small objects you may get tempted to use the reduced footprint
- > of a (1 or 2 byte) tag instead of a sizeof(ptr) vptr.
- > It is also slightly faster to load these unions from a binary file
- > than from a stream, allocate, dispatch and construct every single
- > object and retrieve every single member.
-
- In practice, alignment restrictions are likely to mean that you loose at
- least the size of a pointer even if you declare the tag as a byte.
-
- They advantage of using an integral constant tag is non-negligible when
- writing to a file, but since in practice, you cannot simply write a
- binary image to a file directly anyway, I don't see this as a great
- problem.
-
- > /* union with longlong as member */
- >
- > DB> If you are lucky to have some native long long datatype, then this
- > DB> would be legal code. If you already had to implement your own
- > DB> class longlong, now you lost the chance to use it (here).
- >
- > JK> This is a problem, but... how would the compiler know when to call
- > JK> the constructor/destructor of your longlong?
- >
- > Sorry for the wrong sample, longlong may work with trivial c/dtor and
- > copy operations. The same is with some class Complex.
- >
- > Let's reconsider a class "string" and reference-counter features as
- > sideeffects. The answer for your question - how would the compiler
- > know? - came with my conclusion as quoted below: Just tell him.
- > Here the union constructor itself gets responsible for construction as
- > the correct union variant - e.g. choose the correct discriminator tag,
- > like "empty".
-
- The problem is that unions (C and C++ unions, at least), don't have
- discriminator tags. If you add one, it is no longer a union.
-
- > DB> I would generally prefer " ... constructors and destructor of member
- > DB> objects are ignored, if not explicitly called by the union's ctor/dtor.
- > DB> The union's implicit default copy constructor / assignment does a
- > DB> binary copy instead of memberwise copy. Objects <containing a vptr>
- > DB> cannot be member of a union" - Please pardon my shortcut on vptrs.
- >
- > The missing sample for this:
- >
- > class Member {
- > public:
- > Member();
- > // ...
- > };
- > class Other {
- > public:
- > Other();
- > // ...
- > };
- >
- > union Union {
- > Union();
- > Union(int);
- > // ...
- > Member m;
- > Other o;
- > };
- >
- > Union::Union()
- > { // call none of the base member constructors
- > }
- >
- > // call Member::Member() using a wellknown notation
- > Union::Union(int a)
- > : m()
- > { }
- >
- > // deluxe variant - but this would mean a severe extension
- > Union::Union(int tag)
- > : tag==1 ? m() // call Member::Member()
- > : tag==2 ? o() // otherwise call Other::Other()
- > { }
-
- The extension was discussed, but not adapted. Ask the Australian
- delegation about discriminated unions.
-
- > c) "A union can be thought of as a class"
- >
- > DB> Here you accept the implications of 12.8.8 and 12.8.13 on implicitly
- > DB> defined copy constructor and copy assignment. The already trivial
- > DB> copy constructor/assignment of the member objects will then result
- > DB> in one large repetition of copies from and to the same memory locations.
- > DB> To avoid this behaviour I would strongly recommend to implement your
- > DB> own copy constructor or assignment whenever you use a union, because a
- > DB> memberwise copy is usually not desired.
- >
- > JK> Basically, if you study the restrictions on unions carefully, the
- > JK> rules are such that a bitwise copy *must* be legal for assignment and
- > JK> copy construction. This is the only type of copy the compiler can
- > JK> cope with in the absense of a discriminator to tell it which element
- > JK> of the union is valid.
- >
- > JK> IMHO: if you feel that your union needs a copy constructor or an
- > JK> assignment operator, you are probably doing something wrong, in the
- > JK> sense that you are trying to use unions in a way that they are not
- > JK> intended. (As they are defined in the standard. If they were defined
- > JK> differently, they might have different reasonable uses.)
- >
- > I knew, but some compiler implementors forget their homework here.
- > If for any reason (generated source) you have a union with lots of
- > members, you may accidentally get lots of redundant code. This is
- > another reason for implicit bitwise copy.
- >
- > And if the trivialness requirement were removed from the copy
- > operations, like in my (very draft) replacement text quoted above,
- > you would also loose the equivalence.
- >
- > From a discussion outside this newsgroup I finally got a hint on the
- > intention behind the new restrictions: They should ensure a bitwise
- > copy of the union will copy the current union member correctly.
- > This is achieved by forcing bitwise copy for any potential member.
- >
- > Why did you then not stay just with the POD union? With the
- > differentiation between POD union and non-POD union you already
- > got the higher degree of complexity, only to undo this with lots
- > of additional words.
-
- My position was that a union is not a class; it is an entirely different
- type of object, which just happens to have some class-like features.
- The position actually adapted, however, is that a union is a class, with
- a lot of restrictions. (It wasn't adapted because there were
- alternative proposals that were voted on. It was adapted because there
- was no proposal, and this was the closest to what was in the base
- documents, the ARM and the C standard.)
-
- > My first incident with this problem went what I would call a
- > user's way instead of the implementor's sight: How can we use
- > it? Instead of "How to infer the implicit implementation?"
- > Here I felt invited by the WP to use most of the member object
- > assignments and than fell into the trivialness trap.
- >
- > If your intention is bitwise copy as implicit copy for the union
- > itself, why not just call it by its real name instead of hiding
- > behind "trivialness"?
-
- Because the standard does not define the idea of bitwise copy; it does
- define `trivial' (for constructors, destructors, etc.). The business
- concerning bitwise copy really belongs in a rationale.
-
- > "The implicit union copy constructor and copy assignment apply
- > bitwise copy."
- > No trivialness restrictions on the member objects!
-
- But you then need something to specify what types of objects can be
- safely copied with bitwise copy. This is simply begging the point.
-
- There was some discussion about allowing anything in a union, but using
- bitwise copy anyway. This was felt to be far too dangerous.
-
- > If someone then decides to have member objects with other copy
- > constructor or assignment semantics, he/she just has to provide
- > own union copy operations.
- > -----
- >
- > Some new questions:
- >
- > e) "At most one of the member objects can be stored in a union at
- > any time."
- >
- > Has anybody already thought about the memberwise implicit operations in
- > regard to this rule?
- > OK, we'll meet again at the bitwise copy, but this is at least nowhere
- > explicitly mentioned in the WP.
- >
- > -----
- >
- > f)
- >
- > Why is [class.mem] 15 restricted to POD structs as union members?
- > vptrs are already excluded for union members, and I would still
- > ask to exclude them when dropping the trivialness.
-
- References, I suppose. They also cause problems with bitwise copy. Of
- course, a class or a struct with a reference must have a user defined
- constructor, so it presumably cannot be a member of a union (see above).
- --
- James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
- GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
- Conseils, itudes et rialisations en logiciel orienti objet --
- -- A la recherche d'une activiti dans une region francophone
- ---
- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
- Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is
- in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
-